package com.dynamic.mybatis.web.config;

import com.dynamic.mybatis.core.intercept.DynamicMappedStatementHandler;
import com.dynamic.mybatis.core.metadata.DynamicConfiguration;
import com.dynamic.mybatis.core.session.DynamicSqlSessionTemplate;
import com.dynamic.mybatis.web.security.SecurityParameterHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @Description
 * @Author xs
 * @Date 2023/3/21 15:50
 */
@Configuration
@Component
public class DynamicMybatisWebHandlerInitialize implements ApplicationContextAware {
    ApplicationContext applicationContext;

    @Bean
    @ConditionalOnBean(DynamicSqlSessionTemplate.class)
    @ConditionalOnMissingBean
    public SecurityParameterHandler securityParameterIntercept(DynamicSqlSessionTemplate dynamicSqlSessionTemplate) {
        return this.newSecurityParameterIntercept(dynamicSqlSessionTemplate);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        initialize();
    }

    public void initialize() {
        //创建 SecurityParameterIntercept
        SecurityParameterHandler securityParameterHandler = getBean(SecurityParameterHandler.class);
        if (securityParameterHandler == null) {
            securityParameterHandler = this.newSecurityParameterIntercept(applicationContext.getBean(DynamicSqlSessionTemplate.class));
            addBean(securityParameterHandler);
        }


        //将DynamicMappedStatementHandler 加入DynamicConfigure

        DynamicSqlSessionTemplate dynamicSqlSessionTemplate = getBean(DynamicSqlSessionTemplate.class);
        if (dynamicSqlSessionTemplate != null) {
            Map<String, DynamicMappedStatementHandler> intercepts = applicationContext.getBeansOfType(DynamicMappedStatementHandler.class);
            if (intercepts != null && intercepts.size() > 0) {
                DynamicConfiguration dynamicConfiguration = (DynamicConfiguration) dynamicSqlSessionTemplate.getSqlSession().getConfiguration();
                dynamicConfiguration.addMappedStatementHandler(intercepts.values());
            }
        }

    }

    public SecurityParameterHandler newSecurityParameterIntercept(DynamicSqlSessionTemplate dynamicSqlSessionTemplate) {
        SecurityParameterHandler securityParameterIntercept = new SecurityParameterHandler(dynamicSqlSessionTemplate);
        dynamicSqlSessionTemplate.addSqlSessionHandler(securityParameterIntercept);
        return securityParameterIntercept;
    }

    private <T> T getBean(Class<T> clazz) {
        Map<String, T> beans = applicationContext.getBeansOfType(clazz);
        if (beans != null && beans.size() > 0) {
            return applicationContext.getBean(clazz);
        }
        return null;
    }

    public <T> void addBean(T bean) {
        char[] chars = bean.getClass().getSimpleName().toCharArray();
        chars[0] += 32;
        ((DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory()).registerSingleton(String.valueOf(chars), bean);

/*      DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        BeanDefinitionBuilder beanDefinitionBuilder =  BeanDefinitionBuilder.genericBeanDefinition(beanClass, (Supplier) () ->{
            System.out.println(bean.getClass().getName());
            return bean;
        });
        String simpleName = beanClass.getSimpleName();
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        ((GenericApplicationContext) applicationContext).registerBean(simpleName,beanClass,  ()-> bean);
        (((GenericApplicationContext) applicationContext)).registerBeanDefinition(String.valueOf(chars),beanDefinition);
        applicationContext.getAutowireCapableBeanFactory().initializeBean(bean,String.valueOf(chars));
*/
    }

}